package code.example.base.collection.map;

import code.example.tool.LogFactory;
import code.example.tool.SleepUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

/**
 *  WeakHashMap 与HashMap类似，内部采用 数组+链表 保存 key和value对应关系
 *
 *  链表由Entry 保存了key和value,它扩展了WeakReference ,当发生full gc 时，可能会被回收。
 *
 *  经测试：WeakHashMap中保存的key和value,经过一次或几次full gc后，一部分key和value 会被回收：
 *  [GC (Allocation Failure) [PSYoungGen: 2048K->480K(2560K)] 2048K->869K(9728K), 0.0031239 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]
 * map put size:10000
 * [GC (System.gc()) [PSYoungGen: 1607K->488K(2560K)] 1997K->1573K(9728K), 0.0028190 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (System.gc()) [PSYoungGen: 488K->0K(2560K)] [ParOldGen: 1085K->1326K(7168K)] 1573K->1326K(9728K), [Metaspace: 3513K->3513K(1056768K)], 0.0265491 secs] [Times: user=0.08 sys=0.00, real=0.03 secs]
 * after gc call:
 * map size: 9537
 * [GC (System.gc()) [PSYoungGen: 77K->32K(2560K)] 1404K->1358K(9728K), 0.0006979 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (System.gc()) [PSYoungGen: 32K->0K(2560K)] [ParOldGen: 1326K->1298K(7168K)] 1358K->1298K(9728K), [Metaspace: 3515K->3515K(1056768K)], 0.0146759 secs] [Times: user=0.05 sys=0.00, real=0.01 secs]
 * after gc call:
 * map size: 9075
 * [GC (System.gc()) [PSYoungGen: 37K->32K(2560K)] 1335K->1330K(9728K), 0.0012842 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (System.gc()) [PSYoungGen: 32K->0K(2560K)] [ParOldGen: 1298K->882K(7168K)] 1330K->882K(9728K), [Metaspace: 3517K->3517K(1056768K)], 0.0257541 secs] [Times: user=0.05 sys=0.00, real=0.03 secs]
 * after gc call:
 * map size: 1506
 * [GC (System.gc()) [PSYoungGen: 37K->0K(2560K)] 919K->882K(9728K), 0.0004187 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (System.gc()) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 882K->850K(7168K)] 882K->850K(9728K), [Metaspace: 3517K->3517K(1056768K)], 0.0138069 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]
 * after gc call:
 * map size: 1303
 * [GC (System.gc()) [PSYoungGen: 37K->0K(2560K)] 888K->850K(9728K), 0.0004182 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (System.gc()) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 850K->850K(7168K)] 850K->850K(9728K), [Metaspace: 3517K->3517K(1056768K)], 0.0058421 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
 * after gc call:
 * map size: 1303
 * [GC (System.gc()) [PSYoungGen: 37K->0K(2560K)] 887K->850K(9728K), 0.0003460 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (System.gc()) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 850K->848K(7168K)] 850K->848K(9728K), [Metaspace: 3517K->3517K(1056768K)], 0.0141760 secs] [Times: user=0.03 sys=0.00, real=0.01 secs]
 * after gc call:
 * map size: 128
 * Heap
 * PSYoungGen      total 2560K, used 78K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
 * eden space 2048K, 3% used [0x00000000ffd00000,0x00000000ffd139f8,0x00000000fff00000)
 * from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 * to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 * ParOldGen       total 7168K, used 848K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
 * object space 7168K, 11% used [0x00000000ff600000,0x00000000ff6d4320,0x00000000ffd00000)
 * Metaspace       used 3524K, capacity 4504K, committed 4864K, reserved 1056768K
 * class space    used 389K, capacity 392K, committed 512K, reserved 1048576K
 *
 */
public class TestWeakHashMap {
    private boolean  compareSize(Map map){
        LogFactory.getLog().info("map size: "+map.size());
        return map.size() >1000;
    }
    public void test(){
        int count = 10000;
        Map<Integer,Integer > map = new WeakHashMap<Integer,Integer>();
        for(int i=0;i<count;i++){
            map.put(i,i);
        }
        LogFactory.getLog().info("map put size:"+map.size());
        for(int i=0;i<100;i++){
            System.gc();
            LogFactory.getLog().info("after gc call:");
            if(!compareSize(map)){
                break;
            }
        }
    }
    public static void main(String args []) {
        new TestWeakHashMap().test();
    }
}
